/**
 * 随机生成颜色
 * @returns 颜色
 * @example
 * ()=> "#23AAF3"
 */
export const randomColor2 = () => "#" + Math.random().toString(16).slice(2, 8).padEnd(6, "0").toUpperCase();

/**
 * 随机生成颜色
 * @returns hexColor
 * @example
 * ()=> "#23AAF3"
 */
export const randomColor = () => "#" + ((Math.random() * 0xffffff) << 0).toString(16).toUpperCase();


/**
 * 判断是否 十六进制颜色值.
 * @param color 十六进制颜色值
 * @returns boolean
 * @example
 * isHexColor("#333") => true
 */
export const isHexColor = (color: string) => /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color);

/**
 * RGB 颜色值转换为 十六进制颜色值
 * @param r 需要在 [0, 255] 范围内
 * @param g 需要在 [0, 255] 范围内
 * @param b 需要在 [0, 255] 范围内
 * @returns 十六进制颜色值
 */
export function rgbToHex(r: number, g: number, b: number) {
  if (r > 255 || r < 0 || g > 255 || g < 0 || b > 255 || b < 0) {
    throw new RangeError("RGB's value is not in [0, 255]!!");
  }
  const hex = ((r << 16) | (g << 8) | b).toString(16);
  return "#" + new Array(7 - hex.length).join("0") + hex;
}

/**
 * 十六进制颜色值转换为 RGB 颜色值
 * @param hex 十六进制颜色值
 * @param opacity 不透明度，取值范围[0,1]；可选参数
 * @returns RGB 颜色值
 * @example
 */
export function hexToRgba(hex: string, opacity?: number) {
  if (!isHexColor(hex)) {
    throw new RangeError("Hex color is not valid!!");
  }
  let hexColor = hex.substring(1);
  if (hexColor.length === 3) {
    hexColor = hexColor.replace(/(.)/g, "$1$1");
  }
  const r = parseInt(hexColor.substring(0, 2), 16);
  const g = parseInt(hexColor.substring(2, 4), 16);
  const b = parseInt(hexColor.substring(4, 6), 16);
  if (opacity) {
    if (opacity > 1 || opacity < 0) {
      throw new RangeError("Opacity's value is not in [0, 1]!!");
    }
    const alpha = (opacity * 255).toString(16);
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
  }
  return `rgb(${r}, ${g}, ${b})`;
}

export function hexToRGB(hex: string) {
  if (!isHexColor(hex)) {
    throw new RangeError("Hex color is not valid!!");
  }
  var hexx = Number(hex.replace("#", "0x"));
  var r = hexx >> 16;
  var g = (hexx >> 8) & 0xff;
  var b = hexx & 0xff;
  return `rgb(${r}, ${g}, ${b})`;
}

/**
 * 颜色是否是暗灰色
 * @param color 十六进制颜色值
 * @returns boolean
 */
export const colorIsDark = (hexcolor: string) => {
  const [r, g, b] = hexToRgba(hexcolor)
    .replace(/(?:\(|\)|rgba?)*/gi, "")
    .split(",")
    .map((item) => Number(item));
  return r * 0.299 + g * 0.578 + b * 0.114 < 192;
};

/**
 * 根据百分比调整颜色值,使颜色变亮或变暗
 * @param hexcolor 十六进制颜色值
 * @param amount [-100,100] 百分比数
 * @returns 十六进制颜色值
 */
export const changeLightenOrDarken = (hexcolor: string, amount: number) => {
  if (!isHexColor(hexcolor)) {
    throw new RangeError("Hex color is not valid!!");
  }
  hexcolor = hexcolor.substring(1, hexcolor.length);
  amount = Math.trunc((255 * amount) / 100);
  return `#${subtractLight(hexcolor.substring(0, 2), amount)}${subtractLight(
    hexcolor.substring(2, 4),
    amount
  )}${subtractLight(hexcolor.substring(4, 6), amount)}`;
};

const subtractLight = (color: string, amount: number) => {
  //将文本颜色值转换成16进制数值，exaple: parseInt("FF", 16) => 255
  const cc = parseInt(color, 16) + amount;
  const c = cc < 0 ? 0 : cc > 255 ? 255 : cc;
  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
};

/**
 * 根据与背景的对比度确定最佳文本颜色（黑色或白色）
 * @param hexColor
 * @returns
 */
export const calculateBestTextColor = (hexColor: string) => {
  const rgbColor = hexToRgba(hexColor);
  const contrastWithBlack = contrast(rgbColor.split(","), [0, 0, 0]);

  return contrastWithBlack >= 12 ? "#000000" : "#FFFFFF";
};

const contrast = (rgb1: string[], rgb2: number[]) => (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) / (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05);

const luminanace = (r: number, g: number, b: number) => {
  const a = [r, g, b].map((v) => {
    v /= 255;
    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
  });
  return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
};
